
//#include "main.h"
//#include "Cmd.h"
//#include "SMS.h"
#include "OS.h"
#include "App.h"
#include "debug.h"
#include "macros.h"
#include "LPC23xx.h"
#include "SysClock.h"
#include "Sys.h"
#include "string.h" 
#include "VCom.h" 
#include "hardware.h" 


int OS_CurrentAppIndex;

app_t Apps[APP_AMOUNT];

int OS_Call_App( int call_param, exe *App )
{
	if ( App == NULL )
		return -1;

	if ( OS_Find_App(App) == APP_NOT_FOUND )
	{
		if ( APP_STACK_LEVEL >= (APP_STACK_LEVEL_MAX -1) )
		{
			DBG("\n %s: ==========>>> Stack is FULL <<<===========\n",__FUNCTION__);
			return (-1);
		}

		if ( call_param == OS_APP_RESULT_VOID ) /* 0 */
			APP.CallResult = 0;
		else
			APP.CallResult = OS_APP_RESULT;

		APP_STACK_LEVEL++;

		APP.exe = App;
		APP.Status = MS_ACTIVE;
		APP.State = ASTE_START;
		APP.Timer = 0;
		APP.TimerCase = 0;
		APP.SleepTimer = 0;
		APP.Signal = 0;

		return 0;
	}

	DBG("\r %s: this App is already started\r",__FUNCTION__);
	return (-1);
}

void OS_Return( void )
{
	int tmp;
	if ( APP_STACK_LEVEL > 0 )
	{
		APP.exe = NULL;
		tmp = APP.Result;
		APP_STACK_LEVEL--;

		if ( APP.CallResult == OS_APP_RESULT )
			APP.CallResult = tmp; 
		else
			APP.CallResult = 0;
	}
	else
	{
		APP.Status = MS_FINISH;
	}
}

/* return - index of free module */
static int OS_Find_Free ( void )
{
	int i;
	for ( i = 0; i < APP_AMOUNT; i++ )
	{
		if ( Apps[i].App[0].exe == NULL )
		{
			return i;
		}
	}
	
	return NO_FREE_MEM;
}

/* return Index of STARTED MODULE */
int OS_Run_App ( exe *App )
{
	int i = (-1);

	if ( OS_Find_App(App) == APP_NOT_FOUND )
	{
		if ( ( i = OS_Find_Free() ) != NO_FREE_MEM )
		{
			MemSet((unsigned char*)&Apps[i], sizeof(app_t),0);

			Apps[i].App[0].exe = App;
			Apps[i].App[0].Status = MS_ACTIVE;
			Apps[i].App[0].State = ASTE_START;
		}
		else
		{
			DBG("\r %s: NO FREE MEM\r", __FUNCTION__);
			return OS_ERR_NO_FREE_INDEX;
		}
	}
	else
	{
		return OS_ERR_APP_ALREADY_STARTED;
		DBG("\r %s: this App is already started\r",__FUNCTION__);
	}

	return i;
}

int OS_GetAppResult ( int AppIndex )
{
	if ( AppIndex >= APP_AMOUNT )
	{
		return 0;
	}

	return (Apps[AppIndex].App[0].Status == MS_FINISH ? Apps[AppIndex].App[0].Result : 0); 
}


void OS_Init ( void )
{
	int i;

	for ( i = 0; i < APP_AMOUNT; i++ )
	{
		MemSet((unsigned char*)&Apps[i], sizeof(app_t),0);
	}

	/* Application */
/* 	OS_Run_Module(App); */
/* 	OS_Run_Module(CmdProcessor); */
/* 	OS_Run_Module(CommandMonitor); */

}

int OS_Find_App ( exe *App )
{
	int StackLevel;
	int i;

	for ( i = 0; i < APP_AMOUNT; i++ )
	{
		for ( StackLevel = 0; StackLevel <= APP_STACK_LEVEL; StackLevel++ )
		{
			if (Apps[i].App[StackLevel].exe == App )
			{
				return (i | (StackLevel<<8));
			}
			else
				if ( Apps[i].App[StackLevel].exe == NULL )
				{
					break;
				}
		}
	}

	return APP_NOT_FOUND;
}

void OS_App_Timers ( void )
{
	int StackLevel;
	int i;

	for ( i = 0; i < APP_AMOUNT; i++ )
	{
		for ( StackLevel = Apps[i].StackLevel; StackLevel >= 0; StackLevel-- )
		{
			if (Apps[i].App[StackLevel].Timer )
			{
				Apps[i].App[StackLevel].Timer--;
			}

			if (Apps[i].App[StackLevel].SleepTimer )
			{
				Apps[i].App[StackLevel].SleepTimer--;
				if (Apps[i].App[StackLevel].SleepTimer == 0)
				{
					Apps[i].App[StackLevel].Status = MS_ACTIVE;
				}
			}

		}
	}
}

void OS_Sleep(int SleepTime )
{
	APP.Status = MS_SLEEP;
	APP.SleepTimer = SleepTime/SYS_CLOCK__TIMER_0_INTERVAL;
}

int OS_Send_Signal ( exe *App, unsigned short signal )
{
	int app_handle = OS_Find_App(App);

	if ( app_handle == APP_NOT_FOUND )
		return APP_NOT_FOUND;

	int app_stack_level = (app_handle>>8) & 0xFF;
	int app_index = app_handle & 0xFF; 
	
	
	/* send signal to all app in stack */
	int i;

	for(i = app_stack_level; i <= Apps[app_index].StackLevel ; i++)
	{
		Apps[app_index].App[i].Signal = signal;
	}

	return app_handle;
}

int OS_Kill_App ( exe *App )
{
	int app_handle = OS_Find_App(App);

	if ( app_handle == APP_NOT_FOUND )
		return APP_NOT_FOUND;

	int app_index = app_handle & 0xFF; 

	MemSet((unsigned char*)&Apps[app_index], sizeof(app_t),0);
	
	return app_index;
}

void OS_Apps ( void )
{
	int AppIndex;

	for ( AppIndex = 0; AppIndex < APP_AMOUNT; AppIndex++ )
	{
		OS_CurrentAppIndex = AppIndex;

		if ( APP.Status == MS_ACTIVE || APP.Status == MS_SLEEP )
		{
			if ( APP.exe != NULL )
			{
				/* Check for Signal */
				if ( APP.Signal == APP_SIGNAL_CLOSE )
				{
					DBG("\n%s; APP_SIGNAL_CLOSE\n",__FUNCTION__); 
					APP.State = ASTE_FINISH;
					APP.exe();
					return ;
				}
				else
					if ( Sys_Time && APP.Timer == 1 )		/* Check timeout */
					{
						APP.State = APP.TimerCase;
					}

				if ( APP.Status == MS_ACTIVE )
					APP.exe();
			}
		}
		else
			if ( APP.Status == MS_FINISH )
			{
				APP.Status = MS_NOT_ACTIVE;
				APP_STACK_LEVEL = 0;
				APP.exe = NULL;
			}
	}
}















/* int OS_Delete_Module ( MODULE Module ) */
/* { */
/* 	int i = OS_Find_Module(Module);  */
	
/* 	if ( i != MODULE_NOT_FOUND ) */
/* 	{ */
/* 		Modules[i].ModuleInf[0].ModuleName = NULL; */
/* 		Modules[i].Status = MS_NOT_ACTIVE; */
/* 	} */

/* 	return i; */
/* } */

/* int OS_Module_Disable ( MODULE Module ) */
/* { */
/* 	int i = OS_Find_Module( Module );  */
	
/* 	if ( i != MODULE_NOT_FOUND ) */
/* 	{ */
/* 		Modules[i].Status = MS_NOT_ACTIVE; */
/* 	} */

/* 	return i; */
/* } */

/* int OS_Module_Enable ( MODULE Module ) */
/* { */
/* 	int i = OS_Find_Module( Module );  */
	
/* 	if ( i != MODULE_NOT_FOUND ) */
/* 	{ */
/* 		Modules[i].Status = MS_ACTIVE; */
/* 	} */

/* 	return i; */
/* } */

/* /\* int OS_ResetModule ( MODULE Module ) *\/ */
/* /\* { *\/ */
/* /\* 	if ( OS_Find_Module( Module ) ) *\/ */
/* /\* 	{ *\/ */

/* /\* 	} *\/ */
/* /\* } *\/ */
